package cn.com.bluemoon.daps.model.core.file;

import cn.com.bluemoon.daps.common.constant.DapConstant;
import cn.com.bluemoon.daps.common.domain.ResultBean;
import cn.com.bluemoon.daps.common.toolkit.BmAssetUtils;
import cn.com.bluemoon.daps.model.core.cache.ModelCacheHelper;
import cn.com.bluemoon.daps.model.entity.DapDataModel;
import cn.com.bluemoon.daps.model.entity.DapDataModelTable;
import cn.com.bluemoon.daps.standard.api.RemoteSystemCategoryService;
import cn.com.bluemoon.daps.standard.entity.DapSystemCategory;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.google.common.collect.Lists;
import org.apache.commons.lang.StringUtils;
import reactor.util.function.Tuple2;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static cn.com.bluemoon.daps.model.core.file.excel.converter.MyTopicCategoryStringStringConverter.TOPIC_ID_DB_SPLIT_CHAR;
import static cn.com.bluemoon.daps.model.core.file.excel.converter.MyTopicCategoryStringStringConverter.TOPIC_SPLIT_CHAR;

/**
 * 表抽象类
 *
 * @author Jarod.Kong
 * @date 2021/2/5 9:27
 */
public abstract class TableData extends IMetaData<DapDataModelTable>
        implements IConvertToModel<DapDataModelTable> {
    public static final String GROUP_NAME_SPLIT_CHAR = "/";

    public TableData() {

    }

    public TableData(DapDataModelTable table) {
        BmAssetUtils.notNull(table, "源数据库表信息不可为空");
        copyDbProperties0(table);
    }

    // 表中文名
    public abstract String getTableNameZh();

    // 表业务描述
    public abstract String getBizDesc();

    // 标签1 标签2 标签3
    public abstract String getGroupPathName();

    public abstract void setGroupPathName(String groupPathName);

    public abstract void setTopicName(String topicName);

    // 一级主题/二级主题/三级主题
    public abstract String getTopicName();

    public String getGroupId() {
        if (getGroupPathName() != null) {
            String[] groupIds = getGroupPathName().split(GROUP_NAME_SPLIT_CHAR);
            return groupIds[0];
        }
        return null;
    }

    public String getGroupPid() {
        if (getGroupPathName() != null) {
            String[] groupIds = getGroupPathName().split(GROUP_NAME_SPLIT_CHAR);
            if (groupIds.length >= 2) {
                return groupIds[1];
            }
        }
        return null;
    }

    @Override
    public TableData copyDbProperties0(DapDataModelTable table) {
        // 分组
        String groupId = table.getGroupId();
        String groupPid = table.getGroupPid();
        Tuple2<Optional<String>, Optional<String>> groups = ModelCacheHelper.getGroupIdNameAndGroupPidNameCacheByGroupIds(groupId, groupPid);
        String groupPathName = Stream.of(groups.getT2().orElse(null), groups.getT1().orElse(null)).filter(StringUtils::isNotBlank).collect(Collectors.joining(GROUP_NAME_SPLIT_CHAR));
        setGroupPathName(groupPathName);
        // 主题
        String categoryId = table.getCategoryId();
        String topicNamesByIds = ModelCacheHelper.findTopicNamesCacheByIds(categoryId).orElse(null);
        setTopicName(topicNamesByIds);
        return this;
    }

    /**
     * 主题ids-> 主题明
     *
     * @param categoryId id
     */
    protected String findTopicNamesByIds(String categoryId) {
        if (categoryId != null) {
            String[] topicIds = categoryId.split(TOPIC_ID_DB_SPLIT_CHAR);
            ResultBean<List<DapSystemCategory>> categories = SpringUtil.getBean(RemoteSystemCategoryService.class).getSystemCategories(Arrays.asList(topicIds));
            ResultBean<List<String>> topicStrR = categories.convert(s -> s.stream().map(DapSystemCategory::getCodeName).collect(Collectors.toList()));
            List<String> topics = topicStrR.getContent();
            return String.join(TOPIC_SPLIT_CHAR, topics);
        }
        return null;
    }

    @Override
    public ResultBean<DapDataModelTable> convertToModel(DapDataModel model) {
        BmAssetUtils.notNull(model, "定义好模型");

        DapDataModelTable modelTable = new DapDataModelTable();
        modelTable.setId(null);
        // 分组处理
        modelTable.setGroupId(getGroupId());
        modelTable.setGroupPid(getGroupPid());
        modelTable.setDataNewest(1);
        modelTable.setPId("0");
        modelTable.setName(getTableNameZh());
        modelTable.setEngName(getTableName());
        modelTable.setBusinessDesc(getBizDesc());
        modelTable.setDataSourceId(model.getDataSourceId());
        // 计算主题
        if (getTopicName() != null) {
            final Map<String, List<DapSystemCategory>> topicAndCategories = ModelCacheHelper.getTopicAndCategoriesByCache();
            final List<DapSystemCategory> topic2s = topicAndCategories.get(DapConstant.DapStandard.SYSTEM_TOPIC2_NAME);
            final List<DapSystemCategory> categories1 = topicAndCategories.get(DapConstant.DapStandard.SYSTEM_CATEGORY1_NAME);
            final String[] topicsArr = getTopicName().split(TOPIC_SPLIT_CHAR);
            final String topic = StrUtil.trim(topicsArr[0]);
            final String category1 = StrUtil.trim(topicsArr[1]);
            final String c2 = topicsArr.length == 3 ? StrUtil.trim(topicsArr[2]) : null;
            final List<String> topicIds = Lists.newArrayList();
            // 调整结构
            topic2s.stream()
                    .filter(d -> d.getCodeName().equals(topic)).findFirst()
                    .map(t -> {
                        topicIds.add(t.getId());
                        return categories1.stream().filter(c1 -> c1.getCodeName().equals(category1)).findFirst();
                    })
                    .flatMap(c1 -> c1)
                    .map(c1 -> {
                        topicIds.add(c1.getId());
                        if (c2 != null) {
                            return c1.getNextNodes().stream().filter(c3 -> c3.getCodeName().equals(c2)).findFirst();
                        }
                        return Optional.<DapSystemCategory>empty();
                    })
                    .flatMap(c -> c)
                    .ifPresent(c3 -> {
                        topicIds.add(c3.getId());
                    });
            String topicIdsStr = String.join(TOPIC_ID_DB_SPLIT_CHAR, topicIds);
            modelTable.setCategoryId(topicIdsStr);
        }
        modelTable.setWarehouseTb(model.getSysType() == 2);
        modelTable.setDataModelId(model.getId());
        return convertToModel0(modelTable);
    }

    /**
     * 用于转换为dao模型类
     *
     * @param modelTable 转为
     */
    protected abstract ResultBean<DapDataModelTable> convertToModel0(DapDataModelTable modelTable);

    @Override
    public String sheetName() {
        return "表";
    }

    @Override
    public Integer sheetNo() {
        return 0;
    }
}
